﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.Reflection;
using System.Threading;
using System.IO;
using System.Xml;
using System.Data.SqlClient;
using System.Timers;
using System.Net;

namespace LogMonitorAgent
{
    public partial class LogAgent : ServiceBase
    {

        #region "Private Variables"

        static string conString = ConfigurationManager.ConnectionStrings["SecLogConnectionString"].ToString();

        //选择输出的方式：1 = 数据库 2=文件 12 = 数据库和文件一起输出
        private string outputType = "";

        private Boolean m_run;
        public Thread WorkerThread;

        private EventLog m_LogWatcherLog;
        private EventLog m_ApplicationLog;
        private EventLog m_SystemLog;
        private EventLog m_SecurityLog;
        private string m_InfoLogFile;

        private string logMegTxt = "";
        private string logMachine = "";
        private string logSource = "";
        private string logType;
        private string eventID = "";
        private string user = "";
        private string logDate = "";
        private string logTime = "";
        private string logCategory = "";

        private static string applicationOutputType = System.Configuration.ConfigurationManager.AppSettings["ApplicationType"].ToString();
        private static string securityOutputEventID = System.Configuration.ConfigurationManager.AppSettings["SecurityEventID"].ToString();
        private static string systemOutputType = System.Configuration.ConfigurationManager.AppSettings["SystemType"].ToString();
       // private string[] securityOutputEventIDList;

        
        private string localPath = "";

        //发送生存信息的timer
        System.Timers.Timer liveTimer;
        //主机名
        string hostInfo = Dns.GetHostName();


        #endregion



        public LogAgent()
        {
            //securityOutputEventIDList = securityOutputEventID.Split(',');
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            

            localPath = System.Configuration.ConfigurationManager.AppSettings["address"].ToString();
            outputType = System.Configuration.ConfigurationManager.AppSettings["outputType"].ToString();
            m_InfoLogFile = localPath + "\\log_info.txt";
            WorkerThread = new Thread(WatchEventLog);
            WorkerThread.Start();
            LogInfo("LogMonitor started." + "Information file is [" + m_InfoLogFile + "]");

            //开始发送Live信息给数据库。
            if (outputType == "1")
            {
                sendMessage();
            }
            
            liveTimer = new System.Timers.Timer();
            liveTimer.Elapsed += new ElapsedEventHandler(OnLiveTimerTickedEvent);
            liveTimer.Interval = 600000; //注意是毫秒为单位。此为10分钟。
            // sendEmailTimer.Enabled = true;
            liveTimer.Start();
            LogInfo("liveTimer.Start.");



            // LogError("conString=" + conString);
        }

        protected override void OnStop()
        {
            try
            {

                m_run = false;

                m_LogWatcherLog.Close();
                m_LogWatcherLog.Dispose();

                m_ApplicationLog.Close();
                m_ApplicationLog.Dispose();

                m_SystemLog.Close();
                m_SystemLog.Dispose();

                m_SecurityLog.Close();
                m_SecurityLog.Dispose();

                if (!(WorkerThread == null))
                {
                    if (!(WorkerThread.Join(25000)))
                    {
                        EventLog Log = new EventLog("Application");
                        Log.WriteEntry("Failed to Stop Working Thread...", EventLogEntryType.Error);
                        Log.Close();
                        Log.Dispose();
                    }
                }

                LogInfo("LogMonitor stoped." + "Information file is [" + m_InfoLogFile + "]");

                liveTimer.Stop();
                LogInfo("liveTimer.Stop.");

            }
            catch (Exception e)
            {
                EventLog Log = new EventLog("Application");
                Log.WriteEntry("Failed to Stop:" + e.ToString(), EventLogEntryType.Error);
                Log.Close();
                Log.Dispose();
            }

        }

        public void WatchEventLog()
        {
            try
            {
                m_LogWatcherLog = new EventLog();
                try
                {
                    EventLog.CreateEventSource("LogMonitoringService", "Application");
                }
                catch
                {
                }


                m_LogWatcherLog.Close();
                m_LogWatcherLog = new EventLog("Application", ".", "LogMonitoringService");
                m_LogWatcherLog.Source = "LogMonitoringService";

                m_LogWatcherLog.WriteEntry("LogMonitor started." + "Information file is [" + m_InfoLogFile + "]", EventLogEntryType.Information);

               //LogError("LogMonitor started." + "Error file [" + m_ErrorLogFile + "]");

                m_ApplicationLog = new EventLog();
                m_ApplicationLog.Log = "Application";
                // set event handler
                m_ApplicationLog.EntryWritten += new EntryWrittenEventHandler(ApplicationLog_OnEntryWritten);
                m_ApplicationLog.EnableRaisingEvents = true;

                m_SystemLog = new EventLog();
                m_SystemLog.Log = "System";
                // set event handler
                m_SystemLog.EntryWritten += new EntryWrittenEventHandler(SystemLog_OnEntryWritten);
                m_SystemLog.EnableRaisingEvents = true;

                m_SecurityLog = new EventLog();
                m_SecurityLog.Log = "Security";
                // set event handler
                m_SecurityLog.EntryWritten += new EntryWrittenEventHandler(SecurityLog_OnEntryWritten);
                m_SecurityLog.EnableRaisingEvents = true;

                m_run = true;
                while (m_run)
                {
                    Thread.Sleep(10000);
                }
            }
            catch (Exception e)
            {
                EventLog Log = new EventLog("Application");
                Log.WriteEntry("Failed to WatchEventLog:" + e.ToString(), EventLogEntryType.Error);
                Log.Close();
                Log.Dispose();
            }
        }

        private bool LogInfo(string message)
        {
            try
            {


                StreamWriter objWriter = new StreamWriter(m_InfoLogFile, true);

                objWriter.WriteLine(System.DateTime.Now.ToString("MM/dd/yyyy") + " " + System.DateTime.Now.ToString("HH:mm:ss"));
                objWriter.WriteLine(message);
                objWriter.Close();

                return true;
            }
            catch (Exception e)
            {
                LogInfo(e.ToString());
                return false;
            }
        }


        #region StartWatch

        /// <summary>
        /// Retrieves the stats on the last event log entry
        /// </summary>
        /// <param name="logName">Event log to open</param>
        private void GetLogEntryStats(string logName, EventLogEntry entry)
        {
    
            logMegTxt = entry.Message;
            logMachine = entry.MachineName;
            logSource = entry.Source;
            logCategory = entry.Category;
            logType = Convert.ToString(entry.EntryType);
            eventID = entry.InstanceId.ToString();
            user = entry.UserName;
            logDate = entry.TimeGenerated.ToShortDateString();
            logTime = entry.TimeGenerated.ToShortTimeString();

        }


        private void ApplicationLog_OnEntryWritten(object source, EntryWrittenEventArgs e)
        {
            // string logName = watchLog;
            string logName = "Application";
            if (FilterLog(e, logName))
            {
                OutputLog(e, logName);
            }
        }

        /// <summary>
        /// 过滤有关的Log日志。配置情况见config文件。
        /// </summary>
        /// <param name="e"></param>
        /// <param name="logName"></param>
        /// <returns></returns>
        private bool FilterLog(EntryWrittenEventArgs e, string logName)
        {

            string tempType =  Convert.ToString(e.Entry.EntryType);
            if (logName == "Application")
            {
                switch (applicationOutputType)
                {
                    case "Error":
                        if (tempType == "Error") return true;
                        break;
                    case "Warning":
                        if (tempType == "Warning" || tempType == "Error") return true;
                        break;
                    case "ALL":
                        return true;
                    default: 
                        return false;
                        
                }

            }
            else if (logName == "Security")
            {
                if (securityOutputEventID.Contains(e.Entry.InstanceId.ToString()))
                {
                    return true;
                }
                else
                {
                    return false;

                }

            }
            else if (logName == "System")
            {
                switch (systemOutputType)
                {
                    case "Error":
                        if (tempType == "Error") return true;
                        break;
                    case "Warning":
                        if (tempType == "Warning" || tempType == "Error") return true;
                        break;
                    case "ALL":
                        return true;
                    default:
                        return false;

                }
            }


            //缺省返回false.
             return false;


        }



        private void OutputLog(EntryWrittenEventArgs e, string logName)
        {
            GetLogEntryStats(logName, e.Entry);
            if (outputType == "1")//数据库输出
            {
                sendToDB(logName);

            }
            else if (outputType == "2")//文件的方式输出
            {
                LogNotification();
            }
            else if (outputType == "12")//数据库和文件两种方式输出
            {
                sendToDB(logName);
                LogNotification();
            }
            //LogError(logName + " " + e.Entry.Message);
        }


        private void SystemLog_OnEntryWritten(object source, EntryWrittenEventArgs e)
        {

            // string logName = watchLog;
            string logName = "System";

            if (FilterLog(e, logName))
            {
                OutputLog(e, logName);
            }

        }


        private void SecurityLog_OnEntryWritten(object source, EntryWrittenEventArgs e)
        {

            // string logName = watchLog;
            string logName = "Security";
            if (FilterLog(e, logName))
            {
                OutputLog(e, logName);
            }
        }




        private void sendToDB(string logname)
        {

            try
            {
                //string sqlString = "insert into logMessage(logName) values ('" + logname +  "')";

                string sqlString = "insert into logMessage( logName, logMessage, logMachine, logSource, logCategory, logType, eventID, [user],logDate, logTime,recDateTime) values('" + logname + "','" + logMegTxt + "','" + logMachine + "','" + logSource + "','" + logCategory + "','" + logType + "','" + eventID + "','" + user + "','" + logDate + "','" + logTime + "','" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "')";
                //LogError(sqlString);
                InsertTableData(sqlString, conString);
            }
            catch (Exception e)
            {
                LogInfo(e.ToString());
            }



        }

        private void LogNotification()
        {
            string filename = localPath + "\\logDetail.xml";

            if (!System.IO.File.Exists(filename))
                WriteAlertDoc(filename);

            XmlDocument doc = new XmlDocument();
            doc.Load(filename);

            XmlElement elem = doc.CreateElement("alert");
            elem.SetAttribute("dateTime", logDate+logTime);
            //elem.SetAttribute("time", logTime);
            elem.SetAttribute("type", logType);
            elem.SetAttribute("category", logCategory);
            elem.SetAttribute("source", logSource);
            elem.SetAttribute("eventid", eventID);
            elem.SetAttribute("user", user);
            elem.InnerText = logMegTxt;

            doc.DocumentElement.AppendChild(elem);
            doc.Save(filename);
        }

        private void WriteAlertDoc(string filename)
        {
            XmlTextWriter writer = new XmlTextWriter(filename, System.Text.Encoding.UTF8);
            writer.Formatting = Formatting.Indented;
            writer.WriteStartDocument();

            writer.WriteStartElement("alerts");
            writer.WriteEndElement();
            writer.WriteEndDocument();

            writer.Flush();
            writer.Close();
        }

        #endregion StartWatch


        /// <summary>
        /// InsertTableData
        /// </summary>
        /// <param name="strSql"></param>
        /// <param name="conString"></param>
        public static void InsertTableData(string strSql, string conString)
        {

            using (SqlConnection connection = new SqlConnection(conString))
            {
                connection.Open();
                SqlCommand command = new SqlCommand(strSql, connection);
                command.CommandType = CommandType.Text;

                command.ExecuteNonQuery();
            }

        }

        /// <summary>
        /// 定时器运行。
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        private void OnLiveTimerTickedEvent(object source, ElapsedEventArgs e)
        {
            //开始发送Live信息给数据库。
            if (outputType == "1")
            {
                sendMessage();
            }
        }

        /// <summary>
        /// 发送Live信息给数据库。
        /// </summary>
        private void sendMessage()
        {
            try
            {
                string selectstring = "SELECT count(*) as rid FROM [seclog].[dbo].[HostLiveMessage] where host = '" + hostInfo + "'";
                int nowID; 
                DataSet selectResultDS = SqlHelper.SqlHelper.GetDataSet(selectstring, conString);
                nowID = int.Parse(selectResultDS.Tables[0].Rows[0]["rid"].ToString());


                if (nowID == 1)//update有关信息即可
                {
                    selectstring = "update  [seclog].[dbo].[HostLiveMessage] set [LastLiveTime]='" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "' where [Host] ='" + hostInfo + "'";

                }
                else if (nowID == 0)//需要Insert信息
                {
                    selectstring = "insert into  [seclog].[dbo].[HostLiveMessage]([Host],[LastLiveTime]) values('" + hostInfo + "','" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "')";

                }
                
                selectResultDS = SqlHelper.SqlHelper.GetDataSet(selectstring, conString);
                             
            }
            catch (Exception ex)
            {
                LogInfo(ex.ToString());
            }
        }    

    }
}
